home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / TimerQueue.java < prev    next >
Text File  |  1998-06-30  |  6KB  |  244 lines

  1. /*
  2.  * @(#)TimerQueue.java    1.21 98/06/08
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15.  
  16. /**
  17.  * Internal class to manage all Timers using one thread.
  18.  *
  19.  *
  20.  * @version 1.21 06/08/98
  21.  * @author Dave Moore
  22.  */
  23.  
  24. package com.sun.java.swing;
  25.  
  26. import java.util.*;
  27.  
  28. /** Private class to manage a queue of Timers. The Timers are chained
  29.   * together in a linked list sorted by the order in which they will expire.
  30.   */
  31. class TimerQueue implements Runnable {
  32.     Timer firstTimer;
  33.     boolean running;
  34.  
  35.     private static final Object sharedInstanceKey = new StringBuffer("TimerQueue.sharedInstanceKey");
  36.     private static final Object expiredTimersKey = new StringBuffer("TimerQueue.expiredTimersKey");
  37.  
  38.     public TimerQueue() {
  39.         super();
  40.  
  41.         // Now start the TimerQueue thread.
  42.         start();
  43.     }
  44.  
  45.     public static TimerQueue sharedInstance() {
  46.         synchronized (TimerQueue.class) {
  47.             TimerQueue sharedInst = (TimerQueue)
  48.                 SwingUtilities.appContextGet(sharedInstanceKey);
  49.             if (sharedInst == null) {
  50.                 sharedInst = new TimerQueue();
  51.                 SwingUtilities.appContextPut(sharedInstanceKey, 
  52.                                              sharedInst);
  53.             }
  54.             return sharedInst;
  55.         }
  56.     }
  57.  
  58.     synchronized void start() {
  59.         if (running) {
  60.             throw new RuntimeException("Can't start a TimerQueue that is already running");
  61.         } else {
  62.             Thread timerThread = new Thread(this, "TimerQueue");
  63.  
  64.             try {
  65.                 timerThread.setDaemon(true);
  66.             } catch (SecurityException e) {
  67.             }
  68.             timerThread.start();
  69.             running = true;
  70.         }
  71.     }
  72.  
  73.     synchronized void stop() {
  74.         running = false;
  75.         notify();
  76.     }
  77.  
  78.     synchronized void addTimer(Timer timer, long expirationTime) {
  79.         Timer previousTimer, nextTimer;
  80.  
  81.         // If the Timer is already in the queue, then ignore the add.
  82.         if (timer.running) {
  83.             return;
  84.     }
  85.  
  86.         previousTimer = null;
  87.         nextTimer = firstTimer;
  88.  
  89.         // Insert the Timer into the linked list in the order they will
  90.         // expire.  If two timers expire at the same time, put the newer entry
  91.         // later so they expire in the order they came in.
  92.  
  93.         while (nextTimer != null) {
  94.             if (nextTimer.expirationTime > expirationTime)
  95.                 break;
  96.  
  97.             previousTimer = nextTimer;
  98.             nextTimer = nextTimer.nextTimer;
  99.         }
  100.  
  101.         if (previousTimer == null)
  102.             firstTimer = timer;
  103.         else
  104.             previousTimer.nextTimer = timer;
  105.  
  106.         timer.expirationTime = expirationTime;
  107.         timer.nextTimer = nextTimer;
  108.         timer.running = true;
  109.         notify();
  110.     }
  111.  
  112.     synchronized void removeTimer(Timer timer) {
  113.         boolean found;
  114.         Timer previousTimer, nextTimer;
  115.  
  116.         if (!timer.running)
  117.             return;
  118.  
  119.         previousTimer = null;
  120.         nextTimer = firstTimer;
  121.         found = false;
  122.  
  123.         while (nextTimer != null) {
  124.             if (nextTimer == timer) {
  125.                 found = true;
  126.                 break;
  127.             }
  128.  
  129.             previousTimer = nextTimer;
  130.             nextTimer = nextTimer.nextTimer;
  131.         }
  132.  
  133.         if (!found)
  134.             return;
  135.  
  136.         if (previousTimer == null)
  137.             firstTimer = timer.nextTimer;
  138.         else
  139.             previousTimer.nextTimer = timer.nextTimer;
  140.  
  141.         timer.expirationTime = 0;
  142.         timer.nextTimer = null;
  143.         timer.running = false;
  144.     }
  145.  
  146.     synchronized boolean containsTimer(Timer timer) {
  147.         return timer.running;
  148.     }
  149.  
  150.     // If there are a ton of timers, this method may never return.  It loops
  151.     // checking to see if the head of the Timer list has expired.  If it has,
  152.     // it posts the Timer and reschedules it if necessary.
  153.  
  154.     synchronized long postExpiredTimers() {
  155.         long currentTime, timeToWait;
  156.         Timer timer;
  157.  
  158.         // The timeToWait we return should never be negative and only be zero
  159.         // when we have no Timers to wait for.
  160.  
  161.         do {
  162.             timer = firstTimer;
  163.             if (timer == null)
  164.                 return 0;
  165.  
  166.             currentTime = System.currentTimeMillis();
  167.             timeToWait = timer.expirationTime - currentTime;
  168.  
  169.             if (timeToWait <= 0) {
  170.         try {
  171.             timer.post();  // have timer post an event
  172.         } catch (SecurityException e) {}
  173.  
  174.         // remove the timer from the queue
  175.         removeTimer(timer);
  176.         
  177.         // This tries to keep the interval uniform at the cost of
  178.         // drift.
  179.         if (timer.isRepeats()) {
  180.             addTimer(timer, currentTime + timer.getDelay());
  181.         }
  182.         }
  183.         
  184.         // Allow other threads to call addTimer() and removeTimer()
  185.         // even when we are posting Timers like mad.  Since the wait()
  186.         // releases the lock, be sure not to maintain any state
  187.         // between iterations of the loop.
  188.         
  189.         try {
  190.         wait(1);
  191.         } catch (InterruptedException e) {
  192.         }
  193.     } while (timeToWait <= 0);
  194.     
  195.     return timeToWait;
  196.     }
  197.     
  198.     public synchronized void run() {
  199.         long timeToWait;
  200.  
  201.     try {
  202.         while (running) {
  203.         timeToWait = postExpiredTimers();
  204.         try {
  205.             wait(timeToWait);
  206.         }
  207.         catch (InterruptedException e) { }
  208.         }
  209.     }
  210.     catch (ThreadDeath td) {
  211.         running = false;
  212.         // Mark all the timers we contain as not being queued.
  213.         Timer timer = firstTimer;
  214.         while(timer != null) {
  215.         timer.eventQueued = false;
  216.         timer = timer.nextTimer;
  217.         }
  218.         SystemEventQueueUtilities.restartTimerQueueThread();
  219.         throw td;
  220.     }
  221.     }
  222.  
  223.     public synchronized String toString() {
  224.         StringBuffer buf;
  225.         Timer nextTimer;
  226.  
  227.         buf = new StringBuffer();
  228.         buf.append("TimerQueue (");
  229.  
  230.         nextTimer = firstTimer;
  231.         while (nextTimer != null) {
  232.             buf.append(nextTimer.toString());
  233.  
  234.             nextTimer = nextTimer.nextTimer;
  235.             if (nextTimer != null)
  236.                 buf.append(", ");
  237.         }
  238.  
  239.         buf.append(")");
  240.         return buf.toString();
  241.     }
  242.  
  243. }
  244.